/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session.stateful;

import entity.BranchEntity;
import entity.FnBBranchEntity;
import entity.FnBProductEntity;
import entity.FoodTypeEntity;
import entity.MealEntity;
import entity.PriceControlEntity;
import entity.ProductAvailabilityEntity;
import entity.ProductEntity;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateful;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import util.exception.PriceControlException;

/**
 *
 * @author Dell
 */
@Stateful
@LocalBean
public class ProductSessionBean {

    @PersistenceContext
    EntityManager entityManager;
    String errorMessage;

    public ProductEntity getProductById(Long productId) {
        return entityManager.find(ProductEntity.class, productId);
    }

    public List<FnBProductEntity> getAllProductByBranchId(long branchId) {
        FnBBranchEntity branch = entityManager.find(FnBBranchEntity.class, branchId);
        return branch.getFandBProduct();
    }
    
    public List<ProductEntity> getProductForReservation(long branchId, Date dateReserved) {
        System.out.println("Branch ID is " + branchId);
        List<FnBProductEntity> list = getAllProductByBranchId(branchId); 
        System.out.println("SIZE OF FULL LIST " + list.size());
        List<ProductEntity> result = new ArrayList<ProductEntity>();
        
        //Sunday is 0, Monday is 1... quite our convention number is 0 for default, 1 for Sunday
        long date = dateReserved.getDay()+1;
        System.out.println("DATE IS " + date);
        ProductAvailabilityEntity avail = entityManager.find(ProductAvailabilityEntity.class, date);
        
        List<ProductEntity> temp = avail.getProduct();
        
        for (FnBProductEntity product: list)
            if (temp.contains(product)) {
                System.out.println("ADD");         
                result.add(product);
            }
        return result;
    }

    public List<PriceControlEntity> getListOfPriceControl(long productId) {
        ProductEntity product = entityManager.find(ProductEntity.class, productId);
        return product.getPriceControl();
    }

    public void addPriceControl(long productId, PriceControlEntity priceControl) throws PriceControlException {
        ProductEntity product = entityManager.find(ProductEntity.class, productId);
        List<PriceControlEntity> list = product.getPriceControl();

        if (checkConflictWithList(list, priceControl)) {
            throw new PriceControlException(errorMessage);
        }

        entityManager.persist(priceControl);
        list.add(priceControl);
        priceControl.setProduct(product);
    }

    private boolean checkConflictWithList(List<PriceControlEntity> list, PriceControlEntity priceControl) {
        for (int i = 0; i < list.size(); i++) {
            PriceControlEntity temp = list.get(i);
            int type1 = temp.getType();
            int start1 = temp.getStartTime();
            int end1 = temp.getEndTime();
            Date date1 = temp.getSpecificDate();

            int type2 = priceControl.getType();
            int start2 = priceControl.getStartTime();
            int end2 = priceControl.getEndTime();
            Date date2 = priceControl.getSpecificDate();

            if (type1 == type2 && (type1 != 8 || (type1 == 8 && compareDate(date1, date2)))
                    && timeConflict(start1, end1, start2, end2)) {
                errorMessage = "Time conflict with " + getInfoAboutPriceControl(temp)
                        + ". Your new data is " + getInfoAboutPriceControl(priceControl);
                return true;
            }
        }
        return false;
    }

    private boolean compareDate(Date date1, Date date2) {
        return date1.getYear() == date2.getYear()
                && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate();
    }

    private String getInfoAboutPriceControl(PriceControlEntity temp) {
        return getType(temp.getType(), temp.getSpecificDate())
                + " from " + getSuffix(temp.getStartTime()) + " to " + getSuffix(temp.getEndTime());
    }

    private String getSuffix(int time) {
        if (time == 0) {
            return "12AM";
        }

        if (time == 12) {
            return "12PM";
        }

        if (time < 12) {
            return time + "AM";
        }

        return (time - 12) + "PM";
    }

    private String getType(int type, Date specificDate) {
        switch (type) {
            case 0:
                return "Default";
            case 1:
                return "Monday";
            case 2:
                return "Tuesday";
            case 3:
                return "Wednesday";
            case 4:
                return "Thursday";
            case 5:
                return "Friday";
            case 6:
                return "Saturday";
            case 7:
                return "Sunday";
            default:
                return "Date " + (specificDate.getMonth() + 1) + "/" + specificDate.getDate() + "/" + (specificDate.getYear() + 1900);
        }
    }

    private boolean timeConflict(int start1, int end1, int start2, int end2) {
        if (start1 == start2 || end1 == end2) {
            return true;
        }

        if (start2 < start1) {
            int temp = start1;
            start1 = start2;
            start2 = temp;

            temp = end1;
            end1 = end2;
            end2 = temp;
        }

        if (start1 < start2 && start2 < end1) {
            return true;
        }

        return false;
    }

    public void test() {
        MealEntity meal = new MealEntity();
        entityManager.persist(meal);
    }

    public void removePriceControl(long priceControlId) {
        PriceControlEntity price = entityManager.find(PriceControlEntity.class, priceControlId);
        ProductEntity product = price.getProduct();

        product.getPriceControl().remove(price);
        entityManager.remove(price);
    }

    public void editPriceControl(PriceControlEntity selectedPriceControl) throws PriceControlException {
        List<PriceControlEntity> list = selectedPriceControl.getProduct().getPriceControl();
        PriceControlEntity temp = entityManager.find(PriceControlEntity.class, selectedPriceControl.getId());
        list.remove(temp);

        if (checkConflictWithList(list, selectedPriceControl)) {
            list.add(temp);
            throw new PriceControlException(errorMessage);
        }

        entityManager.merge(selectedPriceControl);
        list.add(selectedPriceControl);
    }

    public ProductAvailabilityEntity[] retrieveAvailListByProductId(Long productId) {
        ProductEntity product = entityManager.find(ProductEntity.class, productId);
        List<ProductAvailabilityEntity> list = product.getProductAvailability();

        ProductAvailabilityEntity[] temp = new ProductAvailabilityEntity[list.size()];
        for (int i = 0; i < temp.length; i++) {
            temp[i] = list.get(i);
        }

        return temp;
    }

    public void editAvail(ProductEntity product, ProductAvailabilityEntity[] selectedAvail) {
        List<ProductAvailabilityEntity> list = product.getProductAvailability();

        while (!list.isEmpty()) {
            ProductAvailabilityEntity avail = list.get(0);
            list.remove(0);
            avail.getProduct().remove(product);
            entityManager.merge(avail);
            entityManager.flush();
        }

        for (int i = 0; i < selectedAvail.length; i++) {
            list.add(selectedAvail[i]);
            selectedAvail[i].getProduct().add(product);
            entityManager.merge(selectedAvail[i]);
        }
        entityManager.merge(product);
    }

    public List<ProductAvailabilityEntity> retrieveAllAvailList() {
        Query query = entityManager.createQuery("SELECT p FROM ProductAvailabilityEntity p");
        return query.getResultList();
    }

    public List<FoodTypeEntity> getFoodType() {
        Query query = entityManager.createQuery("SELECT f FROM FoodTypeEntity f");
        return query.getResultList();
    }

    public double getOnlinePrice(long productId, Date dateReserved, int time) {
        ProductEntity product = entityManager.find(ProductEntity.class, productId);
        List<PriceControlEntity> priceList = product.getPriceControl();

        double normal = -1;
        double dayOfWeek = - 1;
        double specific = -1;
        int date = dateReserved.getDay() + 1;
        System.out.println("DATE IS " + date + " with productId " + productId);

        for (PriceControlEntity c : priceList) {
            int begin = c.getStartTime();
            int end = c.getEndTime();
            if (c.getType() == 8 && fitInSlot(begin, end, time)) {
                Date tempDate = c.getSpecificDate();
                if (compareDate(tempDate, dateReserved)) {
                    specific = c.getPrice();
                    System.out.println("GET specifc price " + specific + " with productId " + productId);
                }
            } else if (date == c.getType() && fitInSlot(begin, end, time)) {                
                dayOfWeek = c.getPrice();
                System.out.println("GET day of week price " + dayOfWeek + " with productId " + productId);
                System.out.println("type is " + c.getType() + " and id " + c.getId());
                
            } else if (c.getType()==0 && fitInSlot(begin, end, time)) {               
                normal = c.getPrice();
                System.out.println("GET normal price " + normal + " with productId " + productId);
            }
        }

        if (specific != - 1) {
            return specific;
        }

        if (dayOfWeek != - 1) {
            return dayOfWeek;
        }

        return normal;
    }

    private boolean fitInSlot(int begin, int end, int time) {
        return begin <= time && time < end;
    }
}
